package com.tanhua.manager.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanhua.manager.domain.AnalysisByDay;
import com.tanhua.manager.domain.Log;
import com.tanhua.manager.mapper.AnalysisMapper;
import com.tanhua.manager.mapper.LogMapper;
import com.tanhua.manager.utils.ComputeUtil;
import com.tanhua.manager.vo.AnalysisChartDataItem;
import com.tanhua.manager.vo.AnalysisSummaryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
public class AnalysisService {

    @Autowired
    private AnalysisMapper analysisMapper;
    @Autowired
    private LogMapper logMapper;

    /**
     * 首页概要信息统计
     */
    public ResponseEntity summary() {
        AnalysisSummaryVO vo = new AnalysisSummaryVO();

        //1. cumulativeUsers 累计用户
        Integer cumulativeUsers = analysisMapper.cumulativeUsers();
        vo.setCumulativeUsers(cumulativeUsers.longValue());

        //2. activePassMonth 过去30天活跃用户
        Date today = DateUtil.endOfDay(new Date());
        Date date30 = DateUtil.beginOfDay(DateUtil.offsetDay(today, -30));
        Integer activePassMonth = analysisMapper.activePassTime(date30, today);
        vo.setActivePassMonth(activePassMonth.longValue());

        //3. activePassWeek 过去7天活跃用户
        Date date7 = DateUtil.beginOfDay(DateUtil.offsetDay(today, -7));
        Integer activePassWeek = analysisMapper.activePassTime(date7, today);
        vo.setActivePassWeek(activePassWeek.longValue());

        //4. newUsersToday 今日新增用户
        AnalysisByDay analysisToday = analysisMapper.selectOne(
                new LambdaQueryWrapper<AnalysisByDay>().eq(AnalysisByDay::getRecordDate, today));
        Integer newUsersToday = analysisToday.getNumRegistered();
        vo.setNewUsersToday(newUsersToday.longValue());

        //5. newUsersTodayRate 今日新增用户涨跌率
        Date yesterday = DateUtil.beginOfDay(DateUtil.offsetDay(today, -1));
        AnalysisByDay analysisYesterday = analysisMapper.selectOne(
                new LambdaQueryWrapper<AnalysisByDay>().eq(AnalysisByDay::getRecordDate, yesterday));
        Integer newUserYesterday = analysisYesterday.getNumRegistered();
        BigDecimal newUsersTodayRate = ComputeUtil.computeRate(newUsersToday.longValue(), newUserYesterday.longValue());
        vo.setNewUsersTodayRate(newUsersTodayRate);

        //6. loginTimesToday 今日登录次数
        Integer loginTimesToday = analysisToday.getNumLogin();
        vo.setLoginTimesToday(loginTimesToday.longValue());

        //7. loginTimesTodayRate 今日登录次数涨跌率
        Integer loginTimesYesterday = analysisYesterday.getNumLogin();
        BigDecimal loginTimesTodayRate = ComputeUtil.computeRate(loginTimesToday.longValue(), loginTimesYesterday.longValue());
        vo.setLoginTimesTodayRate(loginTimesTodayRate);

        //8. activeUsersToday 今日活跃用户
        Integer activeUsersToday = analysisToday.getNumActive();
        vo.setActiveUsersToday(activeUsersToday.longValue());

        //9. activeUsersTodayRate 今日活跃用户涨跌率
        Integer activeUsersYesterday = analysisYesterday.getNumActive();
        BigDecimal activeUsersTodayRate = ComputeUtil.computeRate(activeUsersToday.longValue(), activeUsersYesterday.longValue());
        vo.setActiveUsersTodayRate(activeUsersTodayRate);
        return ResponseEntity.ok(vo);
    }

    /**
     * 统计图
     * @param sd    开始时间
     * @param ed    结束时间
     * @param type  101新增 102活跃用户 103次日留存率
     * @return  List<AnalysisChartDataItem>
     */
    public ResponseEntity usersChartData(Long sd, Long ed, Integer type) {
        //今年开始时间与结束时间
        Date startThisYear = DateUtil.beginOfDay(DateUtil.date(sd));
        Date endThisYear = DateUtil.beginOfDay(DateUtil.date(ed));
        //上一年开始时间与结束时间
        Date startLastYear = DateUtil.offset(startThisYear, DateField.YEAR, -1);
        Date endLastYear = DateUtil.offset(endThisYear, DateField.YEAR, -1);

        //折线图数据集合
        List<AnalysisChartDataItem> thisYearCharaDataItemList = analysisByYear(startThisYear, endThisYear, type);
        List<AnalysisChartDataItem> LastYearCharaDataItemList = analysisByYear(startLastYear, endLastYear, type);

        Map<String, Object> result = new HashMap<>();
        result.put("thisYear", thisYearCharaDataItemList);
        result.put("lastYear", LastYearCharaDataItemList);

        return ResponseEntity.ok(result);
    }

    //折线图数据
    private List<AnalysisChartDataItem> analysisByYear(Date startDate, Date endDate, Integer type){
        //数据分析集合
        List<AnalysisByDay> analysisYearList = analysisMapper.selectList(
                new LambdaQueryWrapper<AnalysisByDay>().
                        between(AnalysisByDay::getRecordDate, startDate, endDate));
        //折线图数据集合
        List<AnalysisChartDataItem> yearItemList = new ArrayList<>();
        //遍历计算
        for (AnalysisByDay analysis : analysisYearList) {
            AnalysisChartDataItem item = new AnalysisChartDataItem();
            //设置数据项名称
            item.setTitle(DateUtil.format(analysis.getRecordDate(), "yyyy-MM-dd"));
            switch (type) {
                case 101:
                    //统计新增
                    item.setAmount(analysis.getNumRegistered().longValue());
                    break;
                case 102:
                    //统计活跃用户
                    item.setAmount(analysis.getNumActive().longValue());
                    break;
                case 103:
                    //次日留存率
                    item.setAmount(analysis.getNumRetention1d().longValue());
                    break;
            }
            yearItemList.add(item);
        }
        return yearItemList;
    }

    //定时统计tb_log中的数据到tb_analysis_by_day
    public void analysis() {
        Date now = new Date();
        String today = DateUtil.format(now, "yyyy-MM-dd");
        String yesterday = DateUtil.offsetDay(now, -1).toString("yyyy-MM-dd");
        //1. 统计今日分析数据
        AnalysisByDay analysis = analysisMapper.selectOne(
                new LambdaQueryWrapper<AnalysisByDay>().eq(AnalysisByDay::getRecordDate, today));
        //2. 判断analysisToday是否存在， 如果不存在新增一条
        if (analysis == null) {
            analysis = new AnalysisByDay();
            analysis.setRecordDate(now);
            analysisMapper.insert(analysis);
        }
        //3. 统计数据
        //统计今日新增用户数据
        QueryWrapper<Log> wrapper = new QueryWrapper<>();
        wrapper.eq("log_time", today);
        wrapper.eq("type", "0102");
        Integer registerNum = logMapper.selectCount(wrapper);
        analysis.setNumRegistered(registerNum);

        //统计今日登录用户数据
        wrapper = new QueryWrapper<>();
        wrapper.eq("log_time", today);
        wrapper.eq("type", "0101");
        Integer loginNum = logMapper.selectCount(wrapper);
        analysis.setNumLogin(loginNum);

        //统计今日活跃用户数据
        wrapper = new QueryWrapper<>();
        wrapper.eq("log_time", today);
        wrapper.select("distinct user_id");
        Integer activeNum = logMapper.selectCount(wrapper);
        analysis.setNumActive(activeNum);

        //统计次日留存率：昨日注册，今日登录
        Integer retentionNum = logMapper.selectRetentionCount(today, yesterday);
        analysis.setNumRetention1d(retentionNum);

        //4. 将数据更新到tb_analysis_by_day库
        analysisMapper.updateById(analysis);
    }
}
